home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / LIBIP / PCCFCTDE.C < prev    next >
C/C++ Source or Header  |  1999-09-11  |  20KB  |  737 lines

  1. /* 
  2.  * pccfctde.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* PCCFCTDE:    functions for PCC decoding
  10.  *            (encoding functions in PCCFCT; and functions common
  11.  *              to both encoding and decoding programs in PCCFCT2)
  12.  *      FUNCTIONS:
  13.  *              PCCREAD, PCCDECODES, PCCDECODE, PCCDETRACK, PCC2XY
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <images.h>             /* images file information */
  20. #include "pcc2.h"               /* header file for PCC programs */
  21.  
  22. int deCode[NDECODE];            /* decode table */
  23. extern unsigned char *fcCode;   /* code storage */
  24. extern long nByteCode;          /* no. bytes in storage */
  25.  
  26.  
  27. /* PCCREAD:     function reads PCC code from file
  28.  *                usage: pccread (filename, &pcc, &nCode, &widthI, &heightI)
  29.  *
  30.  */
  31.  
  32. #define TYPE_STRING 9           /* string for PCC image type */
  33.  
  34. pccread (filename, pcc, nCode, widthI, heightI)
  35.      char *filename;
  36.      unsigned char **pcc;       /* PCC code */
  37.      long *nCode;               /* no. bytes of code */
  38.      long *widthI, *heightI;    /* image size */
  39. {
  40.   FILE *fpIn;
  41.   unsigned char type[TYPE_STRING];
  42.   char string1[20], string2[20];
  43.   static char *typePCC = "TYPE=PCC";
  44.   long w, h;
  45.  
  46. /* open input PCC file */
  47.   if ((fpIn = fopen (filename, "rb")) == NULL) {
  48.     printf ("PCCREAD: cannot open file %s\n", filename);
  49.     return (-1);
  50.   }
  51.  
  52. /* read PCC file header */
  53.   fscanf (fpIn, "%8s", &type);
  54.   //fscanf (fpIn, "%5s %5s %ld %ld", string1, string2, widthI, heightI);
  55.   fscanf (fpIn, "%5s %5s %ld %ld", string1, string2, &w, &h);
  56.   *widthI = w;
  57.   *heightI = h;
  58.   fscanf (fpIn, "%3s %7s %ld\n", string1, string2, nCode);
  59.  
  60.   if ((strcmp (type, typePCC)) != 0) {
  61.     printf ("PCCREAD: input file is not in PCC format.", 1);
  62.     return (-2);
  63.   }
  64.  
  65.   if (((*pcc) = (unsigned char *) malloc (*nCode)) == NULL) {
  66.     printf ("MALLOC: not enough memory -- sorry", 1);
  67.     return (-3);
  68.   }
  69.   fread ((*pcc), sizeof (unsigned char), *nCode, fpIn);
  70.  
  71.   fclose (fpIn);
  72.   return (0);
  73. }
  74.  
  75.  
  76.  
  77. /* PCCDECODES:  function constructs table of PCC decodes
  78.  *            corresponding to sequences of 0, 1, 2, or 3
  79.  *              direction vectors and features endpoint, bifurcation,
  80.  *              and cross
  81.  *                      usage: pccdecodes ()
  82.  *                              extern int decode;
  83.  *
  84.  */
  85.  
  86. int deCode[NDECODE];            /* decode table */
  87.  
  88. pccdecodes ()
  89. {
  90. /* CODE TO PACKED DIRECTION SEGMENTS TABLE */
  91.  
  92.   deCode[1] = 0000;
  93.   deCode[2] = 0100;
  94.   deCode[3] = 0200;
  95.   deCode[4] = 0600;
  96.   deCode[5] = 0700;
  97.   deCode[6] = 0010;
  98.   deCode[7] = 0110;
  99.   deCode[8] = 0210;
  100.   deCode[9] = 0310;
  101.   deCode[10] = 0710;
  102.   deCode[11] = 0020;
  103.   deCode[12] = 0120;
  104.   deCode[13] = 0220;
  105.   deCode[14] = 0320;
  106.   deCode[15] = 0060;
  107.   deCode[16] = 0560;
  108.   deCode[17] = 0660;
  109.   deCode[18] = 0760;
  110.   deCode[19] = 0070;
  111.   deCode[20] = 0170;
  112.   deCode[21] = 0570;
  113.   deCode[22] = 0670;
  114.   deCode[23] = 0770;
  115.   deCode[24] = 0001;
  116.   deCode[25] = 0201;
  117.   deCode[26] = 0101;
  118.   deCode[27] = 0601;
  119.   deCode[28] = 0701;
  120.   deCode[29] = 0011;
  121.   deCode[30] = 0111;
  122.   deCode[31] = 0211;
  123.   deCode[32] = 0311;
  124.   deCode[33] = 0711;
  125.   deCode[34] = 0021;
  126.   deCode[35] = 0121;
  127.   deCode[36] = 0221;
  128.   deCode[37] = 0321;
  129.   deCode[38] = 0421;
  130.   deCode[39] = 0131;
  131.   deCode[40] = 0231;
  132.   deCode[41] = 0331;
  133.   deCode[42] = 0431;
  134.   deCode[43] = 0531;
  135.   deCode[44] = 0071;
  136.   deCode[45] = 0171;
  137.   deCode[46] = 0571;
  138.   deCode[47] = 0671;
  139.   deCode[48] = 0771;
  140.   deCode[49] = 0002;
  141.   deCode[50] = 0102;
  142.   deCode[51] = 0202;
  143.   deCode[52] = 0702;
  144.   deCode[53] = 0012;
  145.   deCode[54] = 0112;
  146.   deCode[55] = 0212;
  147.   deCode[56] = 0312;
  148.   deCode[57] = 0712;
  149.   deCode[58] = 0022;
  150.   deCode[59] = 0122;
  151.   deCode[60] = 0222;
  152.   deCode[61] = 0322;
  153.   deCode[62] = 0422;
  154.   deCode[63] = 0132;
  155.   deCode[64] = 0232;
  156.   deCode[65] = 0332;
  157.   deCode[66] = 0432;
  158.   deCode[67] = 0532;
  159.   deCode[68] = 0242;
  160.   deCode[69] = 0342;
  161.   deCode[70] = 0442;
  162.   deCode[71] = 0542;
  163.   deCode[72] = 0013;
  164.   deCode[73] = 0113;
  165.   deCode[74] = 0213;
  166.   deCode[75] = 0313;
  167.   deCode[76] = 0713;
  168.   deCode[77] = 0023;
  169.   deCode[78] = 0123;
  170.   deCode[79] = 0223;
  171.   deCode[80] = 0323;
  172.   deCode[81] = 0423;
  173.   deCode[82] = 0133;
  174.   deCode[83] = 0233;
  175.   deCode[84] = 0333;
  176.   deCode[85] = 0433;
  177.   deCode[86] = 0533;
  178.   deCode[87] = 0243;
  179.   deCode[88] = 0343;
  180.   deCode[89] = 0443;
  181.   deCode[90] = 0543;
  182.   deCode[91] = 0643;
  183.   deCode[92] = 0353;
  184.   deCode[93] = 0453;
  185.   deCode[94] = 0553;
  186.   deCode[95] = 0653;
  187.   deCode[96] = 0753;
  188.   deCode[97] = 0124;
  189.   deCode[98] = 0224;
  190.   deCode[99] = 0324;
  191.   deCode[100] = 0424;
  192.   deCode[101] = 0134;
  193.   deCode[102] = 0234;
  194.   deCode[103] = 0334;
  195.   deCode[104] = 0434;
  196.   deCode[105] = 0534;
  197.   deCode[106] = 0244;
  198.   deCode[107] = 0344;
  199.   deCode[108] = 0444;
  200.   deCode[109] = 0544;
  201.   deCode[110] = 0644;
  202.   deCode[111] = 0354;
  203.   deCode[112] = 0454;
  204.   deCode[113] = 0554;
  205.   deCode[114] = 0654;
  206.   deCode[115] = 0754;
  207.   deCode[116] = 0464;
  208.   deCode[117] = 0564;
  209.   deCode[118] = 0664;
  210.   deCode[119] = 0764;
  211.   deCode[120] = 0135;
  212.   deCode[121] = 0235;
  213.   deCode[122] = 0335;
  214.   deCode[123] = 0435;
  215.   deCode[124] = 0535;
  216.   deCode[125] = 0245;
  217.   deCode[126] = 0345;
  218.   deCode[127] = 0445;
  219.   deCode[128] = 0545;
  220.   deCode[129] = 0645;
  221.   deCode[130] = 0355;
  222.   deCode[131] = 0455;
  223.   deCode[132] = 0555;
  224.   deCode[133] = 0655;
  225.   deCode[134] = 0755;
  226.   deCode[135] = 0065;
  227.   deCode[136] = 0465;
  228.   deCode[137] = 0565;
  229.   deCode[138] = 0665;
  230.   deCode[139] = 0765;
  231.   deCode[140] = 0075;
  232.   deCode[141] = 0175;
  233.   deCode[142] = 0575;
  234.   deCode[143] = 0675;
  235.   deCode[144] = 0775;
  236.   deCode[145] = 0006;
  237.   deCode[146] = 0106;
  238.   deCode[147] = 0606;
  239.   deCode[148] = 0706;
  240.   deCode[149] = 0346;
  241.   deCode[150] = 0446;
  242.   deCode[151] = 0546;
  243.   deCode[152] = 0646;
  244.   deCode[153] = 0356;
  245.   deCode[154] = 0456;
  246.   deCode[155] = 0556;
  247.   deCode[156] = 0656;
  248.   deCode[157] = 0756;
  249.   deCode[158] = 0066;
  250.   deCode[159] = 0466;
  251.   deCode[160] = 0566;
  252.   deCode[161] = 0666;
  253.   deCode[162] = 0766;
  254.   deCode[163] = 0076;
  255.   deCode[164] = 0176;
  256.   deCode[165] = 0576;
  257.   deCode[166] = 0676;
  258.   deCode[167] = 0776;
  259.   deCode[168] = 0007;
  260.   deCode[169] = 0107;
  261.   deCode[170] = 0207;
  262.   deCode[171] = 0607;
  263.   deCode[172] = 0707;
  264.   deCode[173] = 0017;
  265.   deCode[174] = 0117;
  266.   deCode[175] = 0217;
  267.   deCode[176] = 0317;
  268.   deCode[177] = 0717;
  269.   deCode[178] = 0357;
  270.   deCode[179] = 0457;
  271.   deCode[180] = 0557;
  272.   deCode[181] = 0657;
  273.   deCode[182] = 0757;
  274.   deCode[183] = 0067;
  275.   deCode[184] = 0467;
  276.   deCode[185] = 0567;
  277.   deCode[186] = 0667;
  278.   deCode[187] = 0767;
  279.   deCode[188] = 0077;
  280.   deCode[189] = 0177;
  281.   deCode[190] = 0577;
  282.   deCode[191] = 0677;
  283.   deCode[192] = 0777;
  284.   deCode[193] = 00;
  285.   deCode[194] = 00;
  286.   deCode[195] = 01;
  287.   deCode[196] = 02;
  288.   deCode[197] = 03;
  289.   deCode[198] = 04;
  290.   deCode[199] = 05;
  291.   deCode[200] = 06;
  292.   deCode[201] = 07;
  293.   deCode[202] = 00;
  294.   deCode[203] = 010;
  295.   deCode[204] = 020;
  296.   deCode[205] = 060;
  297.   deCode[206] = 070;
  298.   deCode[207] = 001;
  299.   deCode[208] = 011;
  300.   deCode[209] = 021;
  301.   deCode[210] = 031;
  302.   deCode[211] = 071;
  303.   deCode[212] = 002;
  304.   deCode[213] = 012;
  305.   deCode[214] = 022;
  306.   deCode[215] = 032;
  307.   deCode[216] = 042;
  308.   deCode[217] = 013;
  309.   deCode[218] = 023;
  310.   deCode[219] = 033;
  311.   deCode[220] = 043;
  312.   deCode[221] = 053;
  313.   deCode[222] = 024;
  314.   deCode[223] = 034;
  315.   deCode[224] = 044;
  316.   deCode[225] = 054;
  317.   deCode[226] = 064;
  318.   deCode[227] = 035;
  319.   deCode[228] = 045;
  320.   deCode[229] = 055;
  321.   deCode[230] = 065;
  322.   deCode[231] = 075;
  323.   deCode[232] = 006;
  324.   deCode[233] = 046;
  325.   deCode[234] = 056;
  326.   deCode[235] = 066;
  327.   deCode[236] = 076;
  328.   deCode[237] = 007;
  329.   deCode[238] = 017;
  330.   deCode[239] = 057;
  331.   deCode[240] = 067;
  332.   deCode[241] = 077;
  333.  
  334.   return (0);
  335. }
  336.  
  337.  
  338.  
  339. /* PCCDECODE:   function reads PCC code from code storage, and writes
  340.  *            out decoded image
  341.  *                      usage: pccdecode (image, nX, nY, countflag)
  342.  *              If countflag = 0, lines are decoded to value 255; if 
  343.  *              countflag != 0, lines are decoded into values 1-255
  344.  *              so different lines have different values.
  345.  *
  346.  */
  347.  
  348. pccdecode (image, nX, nY, countflag)
  349.      unsigned char **image;     /* image region to be decoded */
  350.      register long nX, nY;      /* image region size */
  351.      int countflag;             /* different numbers for lines? */
  352. {
  353.   register int iByteCode,       /* code storage incrementor */
  354.     codeWord,                   /* code word contains up to 3 dirn.s */
  355.     x, y;                       /* feature coordinates */
  356.   struct branch1 *branch;       /* stack of branches to be decoded */
  357.   struct branch1 branchTop;     /* first branch */
  358.   long nBranch;                 /* no. of branches in stack */
  359.   int xTrack, yTrack;           /* decode tracking  coord.s */
  360.  
  361.   int imgon = IMGON;
  362.  
  363. /* initialize branches and zero image region */
  364.   nBranch = 0;
  365.   branch = &branchTop;
  366.   branch->previous = branch;
  367.  
  368.   for (y = 0; y < nY; y++)
  369.     for (x = 0; x < nX; x++)
  370.       image[y][x] = 0;
  371.  
  372. /* decode from storage region to original position on screen */
  373.  
  374.   for (iByteCode = 0; iByteCode < nByteCode;) {
  375.     codeWord = (int) fcCode[iByteCode++];
  376.  
  377.     /* if it is a feature: find start location if break, push branches
  378.      *        if junction, pop branches if endpoint */
  379.  
  380.     if (codeWord >= MINFEATCODE) {
  381.       if (countflag) {
  382.         imgon++;
  383.         if (imgon >= 255)
  384.           imgon = 1;
  385.       }
  386.       switch (codeWord) {
  387.       case BIFCODE:
  388.         pccbranch (&branch, xTrack, yTrack, 0);
  389.         nBranch++;
  390.         break;
  391.       case CROSSCODE:
  392.         pccbranch (&branch, xTrack, yTrack, 0);
  393.         nBranch++;
  394.         pccbranch (&branch, xTrack, yTrack, 0);
  395.         nBranch++;
  396.         break;
  397.       case ENDCODE:            /* pop branches */
  398.         if (nBranch > 0) {
  399.           nBranch--;
  400.           branch = branch->previous;
  401.           xTrack = branch->x;
  402.           yTrack = branch->y;
  403.         }
  404.         break;
  405.       case STARTCODE:
  406.         xTrack = (long) *(fcCode + iByteCode)
  407.           | ((long) *(fcCode + iByteCode + 1) << 8);
  408.         iByteCode += 2;
  409.         yTrack = (long) *(fcCode + iByteCode)
  410.           | ((long) *(fcCode + iByteCode + 1) << 8);
  411.         iByteCode += 2;
  412.         image[yTrack][xTrack] = imgon;
  413.         break;
  414.       case LINEBRCODE:
  415.         xTrack = (long) *(fcCode + iByteCode)
  416.           | ((long) *(fcCode + iByteCode + 1) << 8);
  417.         iByteCode += 2;
  418.         yTrack = (long) *(fcCode + iByteCode)
  419.           | ((long) *(fcCode + iByteCode + 1) << 8);
  420.         iByteCode += 2;
  421.         pccbranch (&branch, xTrack, yTrack, 0);
  422.         nBranch++;
  423.         image[yTrack][xTrack] = imgon;
  424.         break;
  425.       case BIFBRCODE:
  426.         xTrack = (long) *(fcCode + iByteCode)
  427.           | ((long) *(fcCode + iByteCode + 1) << 8);
  428.         iByteCode += 2;
  429.         yTrack = (long) *(fcCode + iByteCode)
  430.           | ((long) *(fcCode + iByteCode + 1) << 8);
  431.         iByteCode += 2;
  432.  
  433.         pccbranch (&branch, xTrack, yTrack, 0);
  434.         nBranch++;
  435.         pccbranch (&branch, xTrack, yTrack, 0);
  436.         nBranch++;
  437.         image[yTrack][xTrack] = imgon;
  438.         break;
  439.       case CROSSBRCODE:
  440.         xTrack = (long) *(fcCode + iByteCode)
  441.           | ((long) *(fcCode + iByteCode + 1) << 8);
  442.         iByteCode += 2;
  443.         yTrack = (long) *(fcCode + iByteCode)
  444.           | ((long) *(fcCode + iByteCode + 1) << 8);
  445.         iByteCode += 2;
  446.         pccbranch (&branch, xTrack, yTrack, 0);
  447.         nBranch++;
  448.         pccbranch (&branch, xTrack, yTrack, 0);
  449.         nBranch++;
  450.         pccbranch (&branch, xTrack, yTrack, 0);
  451.         nBranch++;
  452.         image[yTrack][xTrack] = imgon;
  453.         break;
  454.       case LINECODE:
  455.         break;
  456.       case STOPCODE:
  457.         return (0);
  458.       default:
  459.         break;
  460.       }
  461.     }
  462.  
  463.     /* if it is a direction segment, write at proper location */
  464.     else
  465.       pccdetrack (image, &xTrack, &yTrack, codeWord, nX, nY, imgon);
  466.   }
  467.  
  468.   printf ("PCCDECODE: missing STOPCODE in PCC storage \n");
  469.  
  470.   return (0);
  471. }
  472.  
  473.  
  474.  
  475. /* PCCDETRACK:  function decodes codeword and tracks directions
  476.  *            writing back thin lines as original
  477.  *                      usage: nDirns = pccdetrack (image, &x, &y, codeWord)
  478.  *
  479.  */
  480.  
  481. #define DECODE(BITSHIFT) \
  482.         dirn = ((deCode[codeWord] >> BITSHIFT) & 07) + 1; \
  483.         nbrtoxy (dirn, *x, *y, (long *)x, (long *)y); \
  484. if (*x < 0 || *x >= nX){ \
  485. /*  printf ("PCCDETRACK: out of bounds (%4d, %4d)\n", *x, *y); */ \
  486.   *x = nX - 1; \
  487. } \
  488. if (*y < 0 || *y >= nY){ \
  489. /*  printf ("PCCDETRACK: out of bounds (%4d, %4d)\n", *x, *y); */ \
  490.   *y = nY - 1; \
  491. } \
  492.         image[*y][*x] = (unsigned char) imgon
  493.  
  494. pccdetrack (image, x, y, codeWord, nX, nY, imgon)
  495.      long nX, nY;               /* image region size */
  496.      unsigned char **image;     /* image array */
  497.      int *x, *y;                /* input/output line coordinates */
  498.      register long codeWord;    /* code word contains up to 3 directions */
  499.      long imgon;                /* image color  */
  500. {
  501.   register long dirn;           /* direction of next segment */
  502.  
  503. /* 3 direction segments per code word */
  504.   if (MINCODE3 <= codeWord && MAXCODE3 >= codeWord) {
  505.     DECODE (0);
  506.     DECODE (3);
  507.     DECODE (6);
  508.     return (3);
  509.   }
  510.  
  511. /* 2 direction segments per code word */
  512.   if (MINCODE2 <= codeWord && MAXCODE2 >= codeWord) {
  513.     DECODE (0);
  514.     DECODE (3);
  515.     return (2);
  516.   }
  517.  
  518. /* 1 direction segment per code word */
  519.   if (MINCODE1 <= codeWord && MAXCODE1 >= codeWord) {
  520.     DECODE (0);
  521.     return (1);
  522.   }
  523.  
  524. /* 0 direction segment per code word */
  525.   if (codeWord == CODE0) {
  526.     return (0);
  527.   }
  528. }
  529.  
  530.  
  531. /* PCC2XY:      function reads PCC code from code storage, and lists
  532.  *            features and chain codes
  533.  *                      usage: pcc2xy (data, &nData)
  534.  *
  535.  */
  536.  
  537. pcc2xy (data, nData)
  538.      struct point *data;        /* data curve */
  539.      long *nData;               /* no. coords. in data curve */
  540. {
  541.   register int iByteCode,       /* code storage incrementor */
  542.     codeWord;                   /* code word contains up to 3 dirn.s */
  543.   long maxBranch;               /* maximum branching number */
  544.   long maxEdges;                /* total number of edges in graph */
  545.  
  546.   struct branch1 *branch;       /* stack of branches to be decoded */
  547.   struct branch1 branchTop;     /* first branch */
  548.   long nBranch;                 /* no. of branches in stack */
  549.   int xTrack, yTrack;           /* decode tracking  coord.s */
  550.  
  551. /* initialize branches */
  552.   *nData = 0;
  553.   maxBranch = 0;
  554.   maxEdges = 0;
  555.   nBranch = 0;
  556.   branch = &branchTop;
  557.   branch->previous = branch;
  558.  
  559. /* decode from storage region to original position on screen */
  560.   for (iByteCode = 0; iByteCode < nByteCode;) {
  561.     codeWord = (int) fcCode[iByteCode++];
  562.  
  563.     /* if it is a feature: find start location if break, push branches
  564.      *        if junction, pop branches if endpoint */
  565.  
  566.     if (codeWord >= MINFEATCODE) {
  567.       switch (codeWord) {
  568.       case BIFCODE:
  569.         pccbranch (&branch, xTrack, yTrack, 0);
  570.         nBranch++;
  571.         if (nBranch > maxBranch)
  572.           maxBranch = nBranch;
  573.         data[(*nData)++].x = -BIFCODE;
  574.         maxEdges++;
  575.         break;
  576.       case CROSSCODE:
  577.         pccbranch (&branch, xTrack, yTrack, 0);
  578.         nBranch++;
  579.         pccbranch (&branch, xTrack, yTrack, 0);
  580.         nBranch++;
  581.         if (nBranch > maxBranch)
  582.           maxBranch = nBranch;
  583.         data[(*nData)++].x = -CROSSCODE;
  584.         maxEdges++;
  585.         break;
  586.       case ENDCODE:            /* pop branches */
  587.         if (nBranch > 0) {
  588.           nBranch--;
  589.           branch = branch->previous;
  590.           xTrack = branch->x;
  591.           yTrack = branch->y;
  592.           maxEdges++;
  593.         }
  594.         data[(*nData)++].x = -ENDCODE;
  595.         break;
  596.       case STARTCODE:
  597.         data[(*nData)++].x = -STARTCODE;
  598.         xTrack = (long) *(fcCode + iByteCode)
  599.           | ((long) *(fcCode + iByteCode + 1) << 8);
  600.         iByteCode += 2;
  601.         yTrack = (long) *(fcCode + iByteCode)
  602.           | ((long) *(fcCode + iByteCode + 1) << 8);
  603.         iByteCode += 2;
  604.         data[(*nData)].x = xTrack;
  605.         data[(*nData)++].y = yTrack;
  606.         maxEdges++;
  607.         break;
  608.       case LINEBRCODE:
  609.         data[(*nData)++].x = -LINEBRCODE;
  610.         xTrack = (long) *(fcCode + iByteCode)
  611.           | ((long) *(fcCode + iByteCode + 1) << 8);
  612.         iByteCode += 2;
  613.         yTrack = (long) *(fcCode + iByteCode)
  614.           | ((long) *(fcCode + iByteCode + 1) << 8);
  615.         iByteCode += 2;
  616.         pccbranch (&branch, xTrack, yTrack, 0);
  617.         nBranch++;
  618.         if (nBranch > maxBranch)
  619.           maxBranch = nBranch;
  620.         data[(*nData)].x = xTrack;
  621.         data[(*nData)++].y = yTrack;
  622.         maxEdges++;
  623.         break;
  624.       case BIFBRCODE:
  625.         data[(*nData)++].x = -BIFBRCODE;
  626.         xTrack = (long) *(fcCode + iByteCode)
  627.           | ((long) *(fcCode + iByteCode + 1) << 8);
  628.         iByteCode += 2;
  629.         yTrack = (long) *(fcCode + iByteCode)
  630.           | ((long) *(fcCode + iByteCode + 1) << 8);
  631.         iByteCode += 2;
  632.         pccbranch (&branch, xTrack, yTrack, 0);
  633.         nBranch++;
  634.         pccbranch (&branch, xTrack, yTrack, 0);
  635.         nBranch++;
  636.         if (nBranch > maxBranch)
  637.           maxBranch = nBranch;
  638.         data[*nData].x = xTrack;
  639.         data[(*nData)++].y = yTrack;
  640.         maxEdges++;
  641.         break;
  642.       case CROSSBRCODE:
  643.         data[(*nData)++].x = -CROSSBRCODE;
  644.         xTrack = (long) *(fcCode + iByteCode)
  645.           | ((long) *(fcCode + iByteCode + 1) << 8);
  646.         iByteCode += 2;
  647.         yTrack = (long) *(fcCode + iByteCode)
  648.           | ((long) *(fcCode + iByteCode + 1) << 8);
  649.         iByteCode += 2;
  650.         pccbranch (&branch, xTrack, yTrack, 0);
  651.         nBranch++;
  652.         pccbranch (&branch, xTrack, yTrack, 0);
  653.         nBranch++;
  654.         pccbranch (&branch, xTrack, yTrack, 0);
  655.         nBranch++;
  656.         if (nBranch > maxBranch)
  657.           maxBranch = nBranch;
  658.         data[*nData].x = xTrack;
  659.         data[(*nData)++].y = yTrack;
  660.         maxEdges++;
  661.         break;
  662.       case LINECODE:
  663.         break;
  664.       case STOPCODE:
  665.         return (0);
  666.       default:
  667.         break;
  668.       }
  669.     }
  670.  
  671.     /* if it is a direction segment, write at proper location */
  672.     else {
  673.       detrack (&xTrack, &yTrack, codeWord, data, nData);
  674.     }
  675.   }
  676.  
  677.   printf ("PCCDECODE: missing STOPCODE in PCC storage \n");
  678.  
  679.   return (0);
  680. }
  681.  
  682.  
  683.  
  684. /* DETRACK:     function decodes PCC codeword and tracks directions
  685.  *            writing output array of coords.
  686.  *                      usage: nDirns = detrack (&x, &y, codeWord, data,
  687.  *                                              &nData)
  688.  *
  689.  */
  690.  
  691. extern int deCode[NDECODE];     /* decode table */
  692.  
  693. #define DECODE2(BITSHIFT) \
  694.         dirn = ((deCode[codeWord] >> BITSHIFT) & 07) + 1; \
  695.         nbrtoxy (dirn, *x, *y, (long *)x, (long *)y); \
  696.         data[*nData].x = *x; \
  697.         data[(*nData)++].y = *y;
  698.  
  699. detrack (x, y, codeWord, data, nData)
  700.      int *x,                    /* input/output line coordinates */
  701.       *y;
  702.  
  703.      register int codeWord;     /* code word contains up to 3 directions */
  704.  
  705.      struct point *data;        /* data curve */
  706.      long *nData;               /* no. coords. in data curve */
  707.  
  708. {
  709.   register int dirn;            /* direction of next segment */
  710.  
  711. /* 3 direction segments per code word */
  712.   if (MINCODE3 <= codeWord && MAXCODE3 >= codeWord) {
  713.     DECODE2 (0);
  714.     DECODE2 (3);
  715.     DECODE2 (6);
  716.     return (3);
  717.   }
  718.  
  719. /* 2 direction segments per code word */
  720.   if (MINCODE2 <= codeWord && MAXCODE2 >= codeWord) {
  721.     DECODE2 (0);
  722.     DECODE2 (3);
  723.     return (2);
  724.   }
  725.  
  726. /* 1 direction segment per code word */
  727.   if (MINCODE1 <= codeWord && MAXCODE1 >= codeWord) {
  728.     DECODE2 (0);
  729.     return (1);
  730.   }
  731.  
  732. /* 0 direction segment per code word */
  733.   if (codeWord == CODE0) {
  734.     return (0);
  735.   }
  736. }
  737.